package com.codejoys.monitor.web;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.FileUtils;
import com.codejoys.monitor.domain.Device;
import com.codejoys.monitor.domain.DeviceData;
import com.codejoys.monitor.dto.*;
import com.codejoys.monitor.service.DeviceService;
import com.codejoys.monitor.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class DeviceController {
    private static final Logger logger = LoggerFactory.getLogger(DeviceController.class);

    @Autowired
    DeviceService deviceService;

    @Autowired
    UserService userService;

    @GetMapping("/devices/channel/{channel}")
    public BaseResult findByChannel(@PathVariable("channel") String channel) {
        final Device device = deviceService.findByChannel(channel);

        return BaseResult.builder()
                .success()
                .data(device)
                .build();
    }

    @GetMapping("/devices/sn/{sn}")
    public BaseResult findBySn(@PathVariable("sn") String sn) {
        final ConfigDto dto = deviceService.findBySn(sn);

        return BaseResult.builder()
                .success()
                .data(dto)
                .build();
    }

    @GetMapping("/devices")
    public BaseResult findList(
            @RequestParam(name = "page", defaultValue = "1") Integer page,
            @RequestParam(name = "limit", defaultValue = "10") Integer limit,
            DeviceDto device
    ) {

        final PageData<DeviceDto> pageData = deviceService.findList(device, page, limit);

        return BaseResult.builder()
                .success()
                .data(pageData)
                .build();
    }

    @GetMapping("/devices/history/export")
    public void exportHistoryData(DeviceDto device,
        HttpServletResponse response) throws IOException {
            final List<DeviceDto> data = deviceService.findList(device);

        // 文件名
        String fileName = String.format("%s.xlsx", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        final List<DeviceExportData> exportData = data.stream().map(dto -> DeviceExportData.fromDevice(dto)).collect(Collectors.toList());

        EasyExcel.write(response.getOutputStream(), DeviceExportData.class)
                .sheet("历史数据")
                //.includeColumnFiledNames(
                //        Arrays.asList("created", "voltage", "current", "temperature"))
                .doWrite(exportData);
    }

    @GetMapping("/history")
    public BaseResult findHistory(
            @RequestParam(name = "page", defaultValue = "1") Integer page,
            @RequestParam(name = "limit", defaultValue = "10") Integer limit,
            DeviceDto device
    ) {

        final PageData<DeviceDto> pageData = deviceService.findList(device, page, limit);

        return BaseResult.builder()
                .success()
                .data(pageData)
                .build();
    }

    @GetMapping("/status")
    public BaseResult findList(String house) {
        final List<DeviceDto> list = deviceService.statusList(house);

        return BaseResult.builder()
                .success()
                .data(list)
                .build();
    }

    @PutMapping("/devices/{id}/remark")
    public BaseResult remark(@PathVariable("id") Integer id,
                             Authentication auth,
                             @RequestParam("remarks") String remarks) {
        String name = auth.getName();
        final SysUser user = userService.findUserByName(name);

        Device d = new Device();
        d.setId(id);
        d.setUpdated(new Date());
        d.setUpdatedBy(user.getId());
        d.setAgingErrorRemark(remarks);
        d.setNeedRemark((byte) 0);  // 已备注，清除备注标记

        deviceService.updateById(d);

        return BaseResult.builder()
                .success()
                .build();
    }

    @PutMapping("/devices/{id}")
    public BaseResult config(@PathVariable("id") Integer id,
                             Authentication auth,
                             Device device) {
        String name = auth.getName();
        final SysUser user = userService.findUserByName(name);

        device.setId(id);
        device.setUpdated(new Date());
        device.setUpdatedBy(user.getId());

        deviceService.updateById(device);

        return BaseResult.builder()
                .success()
                .build();
    }

    @DeleteMapping("/devices/{id}")
    public BaseResult delete(@PathVariable("id") Integer id,
                             Authentication auth) {

        String name = auth.getName();
        final SysUser user = userService.findUserByName(name);

        deviceService.deleteById(id, user.getId());

        return BaseResult.builder()
                .success()
                .build();
    }

    @PostMapping("/devices")
    public BaseResult batchAdd(@RequestBody List<DeviceDto> devices, Authentication auth) {
        logger.debug("devices: {}", devices);

        String name = auth.getName();
        final SysUser user = userService.findUserByName(name);

        devices.forEach(d -> {
            d.setCreatedBy(user.getId());
            d.setCreated(new Date());
            d.setIsRemoved((byte) 0);
        });

        deviceService.insert(devices, user.getId());

        return BaseResult.builder()
                .success()
                .build();
    }

    @GetMapping("/devices/{id}/logs")
    public BaseResult logs(@PathVariable("id") Integer deviceId,
                           @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
                           @RequestParam("start") Date start) {
        List<DeviceData> data = deviceService.getDeviceLogs(deviceId, start);

        return BaseResult.builder()
                .data(data)
                .success()
                .build();
    }

    @GetMapping("/devices/{id}/logs/export")
    public void exportLogs(@PathVariable("id") Integer deviceId,
         @RequestParam("channel") String channel,
         @RequestParam("sn") String sn,
         @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
         @RequestParam("start") Date start,
         HttpServletResponse response) throws IOException {

        List<DeviceData> data = deviceService.getDeviceLogs(deviceId, start);

        // 文件名
        String fileName = String.format("%s-%s-%s.xlsx", channel, sn,
                new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        EasyExcel.write(response.getOutputStream(), DeviceData.class)
                .sheet("老化数据")
                .includeColumnFiledNames(Arrays.asList("created", "voltage", "current", "temperature"))
                .doWrite(data);
    }

    @GetMapping("/device/status")
    public BaseResult status(String house){
        List<DeviceDto> list= deviceService.getDeviceStatus(house);

        return BaseResult.builder()
                .success()
                .data(list)
                .build();
    }
}
